#!/usr/bin/perl

##############################################################
#
#Purpose: To test if a set of hosts are alive
#
#Usage: get_alive_hosts.pl -f <file name> -n <num_tries = 1>
#
#Restrictions: Requires admin privileges
#
##############################################################

use strict 'vars';
package main;

use Net::Ping;
use Getopt::Std;

use vars qw($opt_n $opt_f);

#get command line options
getopts('n:f:');
if ($opt_f eq "") {
    die "Usage:  get_alive_hosts.pl -f <file name> -n <num_tries = 1>\n";
}
if ($opt_n <= 0) {
    $opt_n = 1;
}

#go over the list of hosts
my %hosts = (), my %hostname = (), my $IP, my $host;
open HOSTFILE, $opt_f;
while ($host = <HOSTFILE>) {
    chomp $host;
    if ($host =~ /^\s*#/) {
	next;
    }
    $IP = my_gethostbyname($host);
    if ($IP eq "NULL") {
	print "Cannot resolve $host, eliminating\n";
    } else {
	$hosts{$host} = 1;
	$hostname{$host} = $IP;
    }
}

#ping $opt_n times if necessary
my $p_icmp, my $p_tcp, my $num_tries;
for ($num_tries = 0; $num_tries < $opt_n; $num_tries++) {

    print "Making attempt number ";
    print $num_tries + 1;
    print "\n";
    
    #done if no more hosts to check
    unless (%hosts) {
	last;
    }

    my %temp_hosts = (), my $host, my $IP;
    foreach $host (keys %hosts) {
	$IP = $hostname{$host};
	$p_icmp = Net::Ping->new("icmp");
	if ($p_icmp->ping($IP, 3)) {
	    print "$host\n";
	    $p_icmp->close();
	} else {
	    $p_tcp = Net::Ping->new("tcp");
	    if ($p_tcp->ping($IP, 3)) {
		print "$host\n";
		$p_tcp->close();
	    } else {
		#print "$host not alive\n";
		$temp_hosts{$host} = 1;
	    }
	}
    }

    %hosts = %temp_hosts;

    print "\n";
}

print "Dead hosts:\n";
foreach $host (keys %hosts) {
    print $host." dead\n";
}

#wrapper to gethostbyname
sub my_gethostbyname {
    my $hostname = @_[0];
    my ($name, $altnames, $addrtype, $len, @addrlist);
    my @addrbytes, my $realaddr;

    if (!(($name, $altnames, $addrtype, $len, @addrlist) 
    			= gethostbyname ($hostname))) {
	return "NULL";	                
    }

    @addrbytes = unpack("C4", $addrlist[0]);
    $realaddr = join (".", @addrbytes);
    return $realaddr;
}
